<template>
  <el-container class="editor-container">
    <el-dialog v-model="showPublishForm" title="发布成功" width="700px">
      <publish-form />
    </el-dialog>
    <preview-form v-model="showPreviewForm" />
    <el-header class="header">
      <div class="page-title">
        <router-link to="/">
          <img class="logo-img" alt="汉德低代码平台" src="../assets/hd-logo.png" />
        </router-link>
        <inline-edit :value="page.title" @change="titleChange">
          <template #default="{ text }">
            <span>{{ text }}</span>
          </template>
        </inline-edit>
      </div>
      <div class="flex-row-vertical">
        <el-button class="menu-btn" type="primary" @click="preview">预览和设置</el-button>
        <el-button class="menu-btn" type="primary" :loading="saveIsLoading" @click="saveWork">保存</el-button>
        <el-button class="menu-btn" type="primary" :loading="isPublishing" @click="publish">发布</el-button>
        <user-profile style="margin-left: 12px"></user-profile>
      </div>
    </el-header>
    <el-container>
      <el-aside width="300px">
        <div class="sidebar-container">
          组件列表
          <components-list :list="defaultTextTemplates" @on-item-click="addItem" />
        </div>
      </el-aside>
      <el-main style="padding: 0 24px 24px; background-color: ghostwhite">
        <div class="preview-container">
          <p>画布区域</p>
          <history-area />
          <div id="canvas-ares" class="preview-list" :class="{ 'canvas-fix': canvasFix }">
            <div class="body-container" :style="page.props">
              <edit-wrapper
                v-for="component in components"
                :id="component.id"
                :key="component.id"
                :hidden="component.isHidden"
                :active="component.id === (currentElement && currentElement.id)"
                :props="component.props"
                @set-active="setActive"
                @update-position="updatePosition"
              >
                <component :is="component.name" v-bind="component.props" :is-editing="true" class="component-wrapper" />
                <!-- <pre>{{ component }}</pre> -->
              </edit-wrapper>
            </div>
          </div>
        </div>
      </el-main>
      <el-aside width="300px" class="settings-panel">
        <el-tabs v-model="activePanel" type="border-card">
          <el-tab-pane label="属性设置" name="component">
            <div v-if="currentElement">
              <edit-group
                v-if="!currentElement.isLocked"
                :props="(currentElement.props as AllComponentProps)"
                @change="handleChange"
              />
              <div v-else>
                <el-empty description="该元素被锁定，无法编辑" />
              </div>
            </div>
            <div v-else>
              <el-empty description="在画布中选择元素并开始编辑" />
            </div>
            <!-- <pre>{{ currentElement && currentElement.props }}</pre> -->
          </el-tab-pane>
          <el-tab-pane label="图层设置" name="layer">
            <layer-list
              :list="components"
              :selected-id="currentElement && currentElement.id"
              @change="handleChange"
              @select="setActive"
            ></layer-list>
          </el-tab-pane>
          <el-tab-pane label="页面设置" name="page">
            <props-table :props="(page.props as AllFormProps)" @change="pageChange" />
            <pre>{{ page.props }}</pre>
          </el-tab-pane>
        </el-tabs>
      </el-aside>
    </el-container>
  </el-container>
</template>

<script lang="ts" setup>
import { pickBy } from 'lodash-es'
import { useEditorStore, ComponentData, AllFormProps } from '@/stores/editor'
import defaultTextTemplates from '@/defaultTextTemplates'
import { AllComponentProps } from '@isameng/lowcode-components'
import HistoryArea from './editor/HistoryArea.vue'
import PublishForm from './editor/PublishForm.vue'
import PreviewForm from './editor/PreviewForm.vue'
import initHotKeys from '@/plugins/hotKeys'
import initContextMenu from '@/plugins/contextMenu'
import useSaveWork from '@/hooks/useSaveWork'
import usePublishWork from '@/hooks/usePublishWork'

export type TabType = 'component' | 'layer' | 'page'

const route = useRoute()
const editor = useEditorStore()

const components = computed(() => editor.components)
const page = computed(() => editor.page)
const currentElement = computed<ComponentData | null>(() => editor.getCurrentElement)

const currentWorkId = route.params.id as string
const activePanel = ref<TabType>('component')
const canvasFix = ref(false)
const showPublishForm = ref(false)
const showPreviewForm = ref(false)

const { saveWork, saveIsLoading } = useSaveWork()
const { publishWork, isPublishing } = usePublishWork()

// 初始化插件函数
initHotKeys()
initContextMenu()

onMounted(() => {
  if (currentWorkId) {
    editor.$reset()
    editor.fetchWork(currentWorkId)
  }
})

const addItem = (component: any) => {
  console.log(component)
  editor.addComponent(component)
}

const setActive = (id: string) => {
  editor.setActive(id)
}

const titleChange = (newTitle: string) => {
  editor.updatePage({ key: 'title', value: newTitle, isRoot: true })
}

const updatePosition = (data: { left: number; top: number; id: string }) => {
  const { id } = data
  // 将 data 的 id 属性剔除
  const updatedData = pickBy<number>(data, (v, k) => k !== 'id')
  // ['left', 'top']
  const keysArr = Object.keys(updatedData) as Array<keyof AllComponentProps>
  // ['30px', '50px']
  const valuesArr = Object.values(updatedData).map(v => v + 'px')
  // 遍历更新数值
  // forEach(updatedData, (v, key) => {
  //   editor.updateComponent({ key, value: v + 'px', id })
  // })
  editor.updateComponent({ key: keysArr, value: valuesArr, id })
}

const handleChange = (e: any) => {
  console.log('event', e)
  editor.updateComponent(e)
}

const pageChange = (e: any) => {
  const { key, value } = e
  console.log('page', e)
  if (key === 'backgroundImage') {
    const { url, height } = value
    editor.updatePage({ key, value: url })
    editor.updatePage({ key: 'height', value: height })
  } else {
    editor.updatePage(e)
  }
}

const publish = async () => {
  editor.setActive('')
  const el = document.getElementById('canvas-ares') as HTMLElement
  // html2canvas 遇到 box-shadow 会出现黑色背景，所以这里在保存截图之前先额外附加个样式，用于清除 box-shadow 属性
  canvasFix.value = true
  await nextTick()
  try {
    await publishWork(el)
    showPublishForm.value = true
  } catch (error) {
    console.error(error)
  } finally {
    canvasFix.value = false
  }
}

const preview = async () => {
  await saveWork()
  showPreviewForm.value = true
}
</script>

<style lang="scss" scoped>
.editor-container {
  height: 100%;
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #122a4e;
  }
  .page-title {
    color: #fff;
    display: flex;
    align-items: center;
    .logo-img {
      margin-right: 10px;
      width: 32px;
      height: 32px;
    }
    .inline-edit {
      span {
        font-weight: 500;
        margin-left: 10px;
        font-size: 16px;
      }
    }
  }

  .menu-btn {
    margin-right: 28px;
  }

  .preview-container {
    padding: 24px;
    margin: 0;
    min-height: 85vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    position: relative;

    .preview-list {
      padding: 0;
      margin: 0;
      min-width: 375px;
      min-height: 200px;
      max-height: 80vh;
      // border: 1px solid #efefef;
      background: #fff;
      overflow-x: hidden;
      overflow-y: auto;
      position: fixed;
      margin-top: 50px;

      &.canvas-fix {
        position: absolute;
        max-height: none;
        .edit-wrapper > * {
          // html2canvas 遇到 box-shadow 会出现黑色背景，所以这里在保存截图之前先额外附加个样式，清除 box-shadow 属性
          box-shadow: none !important;
        }
      }

      .component-wrapper {
        position: static !important; // 因为 editWrapper 组件需要渲染定位相关的交互，static 让子组件里面的 left top 失效
        width: 100% !important; // editWrapper 渲染了子组件的高宽，所以不需要单独设置
        height: 100% !important;
      }
    }
  }
  .settings-panel {
    // :deep(.el-tabs--border-card) {
    //   border-bottom: none;
    // }
    :deep(.el-tabs__content) {
      padding: 0 !important;
    }
  }
}
</style>
